/*
	filename:		CCard.h
	author:			Rico Roberto Zu�iga
	last modified:	9/12/03

	description:	Interface for the CCard class. Handles the card data structure.
 					Some functions based on CardLib.
*/

#ifndef CCARD_H
#define CCARD_H

#include <string>
using std::string;
#include <sstream>
#include <typeinfo>

namespace CardGraphics {
  // if will be using custom cards then these should be initialized outside
  const int CARDWIDTH = 73;
  const int CARDHEIGHT = 97;

  enum CardSymbol {NoSymbol, XSymbol, OSymbol, PlaceholderSymbol};
  int const CARDBACKLOC = 53/* * CARDWIDTH*/; //modify to allow custom card backs
}

namespace Card {

  enum eSuit  { Spades = 0, Hearts = 1, Clubs = 2, Diamonds = 3 };
  enum eValue { Two = 2, Three = 3, Four = 4, Five = 5, Six = 6, Seven = 7,
                Eight = 8, Nine = 9, Ten = 10, Jack = 11, Queen = 12,
                King = 13, Ace = 14 };

  static const char* SuitName[] = {"Spades","Hearts","Clubs","Diamonds",
                                     "Joker"};
  static const char* RankName[] = {"","","Two","Three","Four","Five",
    "Six","Seven","Eight","Nine","Ten","Jack","Queen","King","Ace"};
  static const char* RankInitial[] = {"","","2","3","4","5",
    "6","7","8","9","10","J","Q","K","A"};
}

inline int MAKE_CARD(int myRank, int mySuit)
{
    if(myRank < 2) myRank = 2;
    if(myRank >  14) myRank = Card::Ace;

    if(mySuit < 0)    mySuit = Card::Spades;
    if(mySuit > 3)    mySuit = Card::Diamonds;

    return ( (mySuit * 13) + (myRank - 1) );
}

class CCard
{
public:

    CCard() :
      Idx(1), //two of spades by default
      fFaceUp(true)
    { }

    CCard(int value, int suit) //specify a face value [1-13] and suit [0-3]
    {
        Idx = MAKE_CARD(value, suit);
        fFaceUp = true;
    }

    CCard(int index) //specify a 1-52-joker index
    {
        if(index < 1)  index = 1;
        if(index > 52) index = 53;

        Idx = index;
        fFaceUp = true;
    }

    int Suit() const			{ return ((Idx-1) / 13); }
    int Rank() const			{ return (((Idx-1) % 13) + 2); }
    int Value() const
    {
        int value = Rank();
        if (value > 10) {
            value = (value == Card::Ace) ? 11 : 10;
        }
        return value;
    }
    string Name() const {
      if (IsJoker())
        return "Joker";
      std::ostringstream name;
      name << Card::RankName[Rank()] << " of " << Card::SuitName[Suit()];
      return name.str();
    }
    string Initials() const {
      if (IsJoker())
        return "Joker";
      std::ostringstream initials;
      initials << Card::RankInitial[Rank()] << Card::SuitName[Suit()][0];
      return initials.str();
    }

    bool Equals(const CCard& other) const    { return (Idx == other.Idx); }

    bool IsBlack() const 		{ return Suit() == 0 || Suit() == 2; }
    bool IsRed() const			{ return !IsBlack(); }

    bool FaceUp() const			{ return fFaceUp; }
    bool FaceDown() const		{ return !fFaceUp; }

    bool IsJoker() const			{ return Idx > 52; }

    void SetFaceUp(bool fTrue)	{ fFaceUp = fTrue; }
    void SetIdx(int nIdx)		{ Idx = nIdx; }
    int GetIndex() const                     { return Idx; }

    void SetCardLoc(int lx, int ly)	{ x = lx; y = ly; }

	bool PtInCard(int lx, int ly) const
	{
		if(lx >= x && lx <= CardGraphics::CARDWIDTH + x &&
       ly >= y && ly <= CardGraphics::CARDHEIGHT + y)
			return true;
		else
			return false;
	}

/*	These should be private, but i think it's
	faster if they can be accessed directly,
	just be careful not to accidentally
	modify the values.						*/
	int x;
	int y;

protected:

    int Idx;
    bool	fFaceUp;
};

#endif //CCARD_H
